package org.footballmanager.pandafootball.system.service.impl;

import lombok.extern.slf4j.Slf4j;
import org.footballmanager.pandafootball.common.constants.Constants;
import org.footballmanager.pandafootball.common.util.RandomNumber;
import org.footballmanager.pandafootball.system.domain.FootPerson;
import org.footballmanager.pandafootball.system.domain.FootTeam;
import org.footballmanager.pandafootball.system.domain.FootUser;
import org.footballmanager.pandafootball.system.domain.FootUserPerson;
import org.footballmanager.pandafootball.system.form.impl.FootPersonSearchForm;
import org.footballmanager.pandafootball.system.service.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import tk.mybatis.mapper.entity.Example;

import javax.servlet.http.HttpServletRequest;
import java.text.DecimalFormat;
import java.util.*;

@Slf4j
@Service
public class FootUserPersonServiceImpl extends ServiceImpl<FootUserPerson> implements FootUserPersonService {
    private static final String SORT = "num desc";
	@Autowired
	private FootPersonService footPersonService;
	@Autowired
	private FootTeamService footTeamService;
	@Autowired
	private FootUserService footUserService;
	@Autowired
	private FootZnxService footZnxService;
	@Autowired
	private FootZjService footZjService;
 
	/**
	 * 下放球员
	 */
	@Override
	@Transactional
	public void deletePersonFromMyTeam(Long userId, Long qyId, Integer xycs, HttpServletRequest request){
		FootUserPerson fup = this.findPersonByQyidandXycs(userId, qyId, xycs);
		if(null != fup){
			this.delete(fup.getId(), request);
		}
		List<FootUserPerson> list = this.findFootPersonsByUserIdandQyId(userId, qyId);
		if(list != null && !list.isEmpty()){
			for(FootUserPerson fuperson: list){
				fuperson.setNum(fuperson.getNum() - 1);
				this.updateNotNull(fuperson, request);
			}
		}
	}

	@Override
	@Transactional
	public void deleteAllPerson(Long userId, HttpServletRequest request) {
        Example example = new Example(FootUserPerson.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo(Constants.USERID, userId);
		List<FootUserPerson> list = this.findall(example);
		if(list != null && !list.isEmpty()){
			for(FootUserPerson fup: list){
				this.delete(fup.getId(), request);
			}
		}
	}
	
	/**
	 * 随机分配评分75以下的球员
	 */
	@Override
	@Transactional
	public void randomLow75(Long userId, HttpServletRequest request){
		Random r = new Random();
		FootPersonSearchForm footPersonSearchForm = new FootPersonSearchForm();
        processWhiteMan(footPersonSearchForm, r, userId, request);
        processGreenMan(footPersonSearchForm, r, userId, request);
        processBlueMan(footPersonSearchForm, r, userId, request);
        processPurpleMan(footPersonSearchForm, r, userId, request);
	}

	private void processWhiteMan(FootPersonSearchForm footPersonSearchForm, Random r, Long userId, HttpServletRequest request){
		footPersonSearchForm.setDjId(1L);
        List<FootPerson> list = footPersonService.findall(footPersonSearchForm);
        if(list == null || list.isEmpty()) {
			return;
		}
		Set<Integer> set1 = new HashSet<>();
		Set<Integer> set2 = new HashSet<>();
		Set<Integer> set3 = new HashSet<>();
		Set<Integer> set4 = new HashSet<>();
		while(true){
			Integer g = r.nextInt(list.size() - 1);
			processWz(g, list, set1, set2, set3, set4);

			if((set1.size() == 1 && set2.size() == 2) && (set3.size() == 4 && set4.size() == 4)){
				break;
			}
		}
		set1.addAll(set2);
		set1.addAll(set3);
		set1.addAll(set4);
		for(Integer h: set1){
			FootPerson fp = list.get(h);
			this.saveUserPerson(userId, fp, request);
		}
    }

    private void processWz(Integer g, List<FootPerson> list, Set<Integer> set1, Set<Integer> set2, Set<Integer> set3, Set<Integer> set4){
		FootPerson fp = list.get(g);
		boolean flag1 = "DMF".equals(fp.getWzbm()) || "AMF".equals(fp.getWzbm());
		boolean flag2 = "LMF".equals(fp.getWzbm()) || "RMF".equals(fp.getWzbm());
		boolean flag3 = "CF".equals(fp.getWzbm()) || "SS".equals(fp.getWzbm());
		boolean flag4 = "LWF".equals(fp.getWzbm()) || "RWF".equals(fp.getWzbm());
		if("GK".equals(fp.getWzbm()) && set1.isEmpty()){
			set1.add(g);
		}else if(("CB".equals(fp.getWzbm()) || "LB".equals(fp.getWzbm()) ||
				"RB".equals(fp.getWzbm())) && set3.size() < 4){
			set3.add(g);
		}else if((flag1 || flag2) && set4.size() < 4){
			set4.add(g);
		}else if((flag3 || flag4) && set2.size() < 2){
			set2.add(g);
		}
	}

    private void processGreenMan(FootPersonSearchForm footPersonSearchForm, Random r, Long userId, HttpServletRequest request){
		footPersonSearchForm.setDjId(2L);
		List<FootPerson> listlv = footPersonService.findall(footPersonSearchForm);
        if(listlv != null && !listlv.isEmpty()){
            Set<Integer> set = new HashSet<>();
            while(true){
                set.add(r.nextInt(listlv.size() - 1));
                if(set.size() == 4){
                    break;
                }
            }
            for(Integer i : set){
                FootPerson fp = listlv.get(i);
                this.saveUserPerson(userId, fp, request);
            }
        }
    }

    private void processBlueMan(FootPersonSearchForm footPersonSearchForm, Random r, Long userId, HttpServletRequest request){
		footPersonSearchForm.setDjId(2L);
		List<FootPerson> listlan = footPersonService.findall(footPersonSearchForm);
        if(listlan != null && !listlan.isEmpty()){
            Set<Integer> set = new HashSet<>();
            while(true){
                set.add(r.nextInt(listlan.size() - 1));
                if(set.size() == 2){
                    break;
                }
            }
            for(Integer i : set){
                FootPerson fp = listlan.get(i);
                this.saveUserPerson(userId, fp, request);
            }
        }
    }

    private void processPurpleMan(FootPersonSearchForm footPersonSearchForm, Random r, Long userId, HttpServletRequest request){
		footPersonSearchForm.setDjId(4L);
		List<FootPerson> listzi = footPersonService.findall(footPersonSearchForm);
        if(listzi != null && !listzi.isEmpty()){
            FootPerson fp = listzi.get(r.nextInt(listzi.size() - 1));
            this.saveUserPerson(userId, fp, request);
        }
    }

	/**
	 * 续约
	 */
	@Override
	public String renew(Long userId, Long qyId, Integer xycs, HttpServletRequest request){
		FootUserPerson fup = this.findPersonByQyidandXycs(userId, qyId, xycs);
		if(null != fup){
			FootTeam team = footTeamService.getTeamByUserid(userId);
			FootPerson fp = footPersonService.get(qyId);
			Double money = Double.valueOf(fp.getQysj()) * 0.5D;
			if(team != null){
				if(money > team.getQdZzj()){
					return "nomoney";
				}
				team.setQdZzj(team.getQdZzj() - money);
				footTeamService.updateNotNull(team, request);
				fup.setXycs(fup.getXycs() + 50);
				this.updateNotNull(fup, request);
				footZnxService.sendZnx(footUserService.getAdminUserid(), team.getUserId(), "因续约球员" +
						fp.getName() + ",扣除€" + 	new DecimalFormat(",###").format(money), null, null, request);
				footZjService.sendZj(team.getUserId(), money, false, "因续约球员" + fp.getName() +
						",扣除€" + new DecimalFormat(",###").format(money) + ",当前的球队总资金为:€" +
						new DecimalFormat(",###").format(team.getQdZzj()), request);
				return "ok";
			}else{
				return "noteam";
			}
		}
		return "noperson";
	}

	@Override
	public List<FootUserPerson> findPersonByUserId(Long userId) {
        Example example = new Example(FootUserPerson.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo(Constants.USERID, userId);
        example.orderBy("main desc, xycs desc");
		return this.findall(example);
	}

	@Override
	public List<FootPerson> findFootPersonByUserId(Long userId, HttpServletRequest request) {
		if(StringUtils.isEmpty(userId)) {
            return Collections.emptyList();
        }
        List<FootPerson> list = new ArrayList<>();
        List<FootUserPerson> fuplist = this.findPersonByUserId(userId);
        if(null == fuplist || fuplist.isEmpty()) {
            return Collections.emptyList();
        }
        for(FootUserPerson fup: fuplist){
            FootPerson fp = footPersonService.get(fup.getQyId());
            if(null != fp){
                fp.setUpTimes(fup.getUpTimes());
                fp.setPower(fup.getPower());
                fp.setGpzt(fup.getGpzt());
                fp.setFupId(fup.getId());
                fp.setMain(fup.getMain());
                fp.setXycs(fup.getXycs());
                list.add(fp);
            }else{
                if(fup.getQyId() != null){
                    this.delete(fup, request);
                }
            }
        }
        list.sort(Comparator.comparing(FootPerson::getDjId));
        return list;
	}

	@Override
	public void autoDeletePerson(Long userId, HttpServletRequest request) {
		List<FootUserPerson> list = this.findPersonByUserId(userId);
		for(FootUserPerson fup: list){
			fup.setXycs(fup.getXycs() - 1);
			this.updateNotNull(fup, request);
			if(fup.getXycs().equals(0)){
				FootPerson fp = footPersonService.get(fup.getQyId());
				this.delete(fup.getId(), request);
				footZnxService.sendZnx(footUserService.getAdminUserid(), userId,
    					"由于球员" + (fp.getName() == null ? fp.getYw() : fp.getName()) + 
    					"的续约次数已到,您没有及时续约,系统自动解约该球员", null, null, request);
			}
		}
	}

	@Override
	public void addUseTimes(Long userId, HttpServletRequest request) {
		List<FootUserPerson> list = this.findPersonByUserId(userId);
		if(list != null && !list.isEmpty()){
			for(FootUserPerson fup: list){
				fup.setXycs(fup.getXycs() + 1);
				this.updateNotNull(fup, request);
			}
		}
	}

	@Override
	public void saveUserPerson(Long userId, FootPerson fp, HttpServletRequest request) {
		FootUserPerson fup = new FootUserPerson();
		fup.setQyId(fp.getId());
		fup.setYw(fp.getYw());
		fup.setUserId(userId);
		fup.setXycs(50);
		fup.setPower((double)fp.getPf());
		fup.setMain(true);
		//获取球队人数
		List<FootUserPerson> list = this.findFootPersonsByUserIdandQyId(userId, fp.getId());
		fup.setNum(list.size() + 1);
		this.save(fup, request);
	}

	@Override
	public List<FootPerson> findCanGpPerson(Long userId) {
		List<FootPerson> list = new ArrayList<>();
		Example example = new Example(FootUserPerson.class);
		Example.Criteria criteria = example.createCriteria();
		criteria.andEqualTo(Constants.USERID, userId);
		List<FootUserPerson> fupList = this.findall(example);
		if(fupList != null && !fupList.isEmpty()){
			for(FootUserPerson fup: fupList){
				if(fup.getXycs() > 0){
					FootPerson fp = footPersonService.get(fup.getQyId());
					fp.setFupId(fup.getId());
					fp.setXycs(fup.getXycs());
					list.add(fp);
				}
			}
		}
		return list;
	}

	@Override
	public List<FootUserPerson> findFootPersonsByUserIdandQyId(Long userId, Long qyId) {
        Example example = new Example(FootUserPerson.class);
        Example.Criteria criteria = example.createCriteria();
		if(null != userId){
            criteria.andEqualTo(Constants.USERID, userId);
		}
		criteria.andEqualTo("qyId", qyId);
		example.orderBy(SORT);
		return this.findall(example);
	}

	@Override
	public int checkMainPerson(FootUser user) {
		int result = 0;
		List<FootUserPerson> list = this.findPersonByUserId(user.getId());
		if(null != list && !list.isEmpty()){
			for(FootUserPerson fup: list){
				if(fup.getMain()){
					result += 1;
				}
			}
		}
		return result;
	}

	@Override
	public double getPower(Long userId, HttpServletRequest request) {
		Double result = 0D;
		List<FootPerson> list = this.findFootPersonByUserId(userId, request);
		if(null != list && !list.isEmpty()){
			for(FootPerson fp: list){
				if(fp.getMain()){
					result += Double.valueOf(fp.getPf());
				}
			}
		}
		return result;
	}

    /**
     * 	同样2名球员可以升级，升级后球员战力增长20%  同可升级5次
     *	1+1=2     		成功率100%
     *	2+1=3    		成功率90%
     *	3+1=4     2+2=4   成功率80%
     *	4+1=5     3+2=5   成功率70%
     *	升级失败 低级别球员消失  高级别球员不变
     *	升级成功 低级别球员消失  高级别球员升级
     */
	@Override
	public String compose(Long fupId1, Long fupId2, HttpServletRequest request) {
		FootUserPerson fup1 = this.get(fupId1);
		FootUserPerson fup2 = this.get(fupId2);
		int result = RandomNumber.randomNumber();
		if(!fup1.getQyId().equals(fup2.getQyId())) {
            return "合成球员必须为同一球员";
        }
        //看球员是否有等级差
        if(fup1.getPower() > fup2.getPower()){
			return processGreaterThan(fup1, fup2, request, result);
        }else if(fup1.getPower().equals(fup2.getPower())){
        	return processEquals(fup1, fup2, request, result);
        }else{
        	return processLessThan(fup1, fup2, request, result);
        }
	}

	private boolean processBoolean(FootUserPerson fup1, Integer num1, FootUserPerson fup2, Integer num2){
		return fup1.getUpTimes().equals(num1) && fup2.getUpTimes().equals(num2);
	}

	private String processLessThan(FootUserPerson fup1, FootUserPerson fup2, HttpServletRequest request, int result) {
		boolean flag1 = processBoolean(fup1, 1, fup2, 2);
		boolean flag2 = processBoolean(fup1, 1, fup2, 3);
		boolean flag3 = processBoolean(fup1, 1, fup2, 4);
		boolean flag4 = processBoolean(fup1, 2, fup2, 3);
		return processFlag(flag1, flag2, flag3, flag4, fup1, fup2, request, result, false);
	}

	private String processEquals(FootUserPerson fup1, FootUserPerson fup2, HttpServletRequest request, int result) {
		if(processBoolean(fup1, 1, fup2, 1) && result <= 100){
			return this.composeSuccess(fup1, fup2, request, true);
		}else if(processBoolean(fup1, 2, fup2, 2) && result <= 80){
			return this.composeSuccess(fup1, fup2, request, true);
		}
		return this.composeFailed(fup2.getId(), request);
	}

	private String processGreaterThan(FootUserPerson fup1, FootUserPerson fup2, HttpServletRequest request, int result) {
		boolean flag1 = processBoolean(fup1, 2, fup2, 1);
		boolean flag2 = processBoolean(fup1, 3, fup2, 1);
		boolean flag3 = processBoolean(fup1, 4, fup2, 1);
		boolean flag4 = processBoolean(fup1, 3, fup2, 2);
		return processFlag(flag1, flag2, flag3, flag4, fup1, fup2, request, result, true);
	}

	private String processFlag(boolean flag1, boolean flag2, boolean flag3, boolean flag4, FootUserPerson fup1, FootUserPerson fup2,
							   HttpServletRequest request, int result, boolean isFup2){
		if(flag1 && result <= 90){
			return this.composeSuccess(fup1, fup2, request, isFup2);
		}else if(flag2 && result <= 80){
			return this.composeSuccess(fup1, fup2, request, isFup2);
		}else if((flag3 || flag4) && result <= 70){
			return this.composeSuccess(fup1, fup2, request, isFup2);
		}
		if(isFup2){
			return this.composeFailed(fup2.getId(), request);
		}else{
			return this.composeFailed(fup1.getId(), request);
		}
	}

	private String composeSuccess(FootUserPerson fup1, FootUserPerson fup2, HttpServletRequest request, boolean isFup2){
		//合成成功
		if(isFup2){
			fup1.setPower(fup1.getPower() * 1.2D);
			fup1.setUpTimes(fup1.getUpTimes() + 1);
			this.updateNotNull(fup1, request);
			this.delete(fup2.getId(), request);
		}else{
			fup2.setPower(fup2.getPower() * 1.2D);
			fup2.setUpTimes(fup2.getUpTimes() + 1);
			this.updateNotNull(fup2, request);
			this.delete(fup1.getId(), request);
		}
		return Constants.OK;
	}
	
	private String composeFailed(Long id, HttpServletRequest request){
		this.delete(id, request);
		return "合成失败";
	}

	@Override
	public FootUserPerson findPersonByQyidandXycs(Long userId, Long qyId, Integer xycs) {
        Example example = new Example(FootUserPerson.class);
        Example.Criteria criteria = example.createCriteria();
		if(null != userId){
            criteria.andEqualTo(Constants.USERID, userId);
		}
        criteria.andEqualTo("qyId", qyId);
		criteria.andEqualTo("xycs", xycs);
		example.orderBy(SORT);
		return this.findByExample(example);
	}

	@Override
	public FootTeam getRandomTeam(FootUser userSession) {
		List<FootUser> list = new ArrayList<>();
		List<FootUser> users = footUserService.getAllWithoutAdmin(null);
		if(users != null && !users.isEmpty()){
			for(FootUser user: users){
				//根据每个用户查看符合天梯赛条件
				if(this.checkMainPerson(user) >= 18 && !user.getNike().equals(userSession.getNike())){
					list.add(user);
				}
			}
		}
		if(!list.isEmpty()){
			//随机取一个球队
			Random r = new Random();
			FootUser user = list.get(r.nextInt(list.size() - 1));
			return footTeamService.getTeamByUserid(user.getId());
		}
		return null;
	}

	@Override
	public boolean findPersonMain(Long userId, FootUserPerson fup) {
        Example example = new Example(FootUserPerson.class);
        Example.Criteria criteria = example.createCriteria();
		if(null != userId){
		    criteria.andEqualTo(Constants.USERID, userId);
		}
		criteria.andEqualTo("qyId", fup.getQyId());
        example.orderBy(SORT);
		List<FootUserPerson> list = this.findall(example);
		if(list != null && !list.isEmpty()){
			for(FootUserPerson fups: list){
				if(fups.getMain()){
					return true;
				}
			}
		}
		return false;
	}

	/**
	 * 根据等级主键获取球员列表
	 *
	 * @param djId 等级主键
	 * @return 球员列表
	 */
	private List<FootPerson> findByDjId(Long djId) {
		return footPersonService.findByDjId(djId);
	}
}
